import $bus from "./bus.js" //事件中央总线
import Vue from "vue"

// 各个国家手机号对照
const phoneObj = {
	"ar-DZ": /^(\+?213|0)(5|6|7)\d{8}$/, //阿拉伯语 (阿尔及利亚)
	"ar-SY": /^(!?(\+?963)|0)?9\d{8}$/, //阿拉伯文 (叙利亚)
	"ar-SA": /^(!?(\+?966)|0)?5\d{8}$/, //阿拉伯文 (沙特阿拉伯)
	"en-US": /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/, //英语 (美国)
	"cs-CZ": /^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/, //捷克语 (捷克共和国)
	"de-DE": /^(\+?49[ \.\-])?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, //德语 (德国)
	"da-DK": /^(\+?45)?(\d{8})$/, //丹麦语 (丹麦)
	"el-GR": /^(\+?30)?(69\d{8})$/, //希腊语 (希腊)
	"en-AU": /^(\+?61|0)4\d{8}$/, //英语 (澳大利亚)
	"en-GB": /^(\+?44|0)7\d{9}$/, //英语 (英国)
	"en-IN": /^(\+?91|0)?[789]\d{9}$/, //英语 (印度)
	"en-NZ": /^(\+?64|0)2\d{7,9}$/, //英语 (新西兰)
	"en-ZA": /^(\+?27|0)\d{9}$/, //英语 (南非)
	"en-ZM": /^(\+?26)?09[567]\d{7}$/, //英语 (赞比亚)
	"es-ES": /^(\+?34)?(6\d{1}|7[1234])\d{7}$/, //西班牙语 (西班牙)
	"fi-FI": /^(\+?358|0)\s?(4(0|1|2|4|5)?|50)\s?(\d\s?){4,8}\d$/, //芬兰语 (芬兰)
	"fr-FR": /^(\+?33|0)[67]\d{8}$/, //法语 (法国)
	"he-IL": /^(\+972|0)([23489]|5[0248]|77)[1-9]\d{6}/, //希伯来语 (以色列)
	"hu-HU": /^(\+?36)(20|30|70)\d{7}$/, //匈牙利语 (匈牙利)
	"it-IT": /^(\+?39)?\s?3\d{2} ?\d{6,7}$/, //意大利语 (意大利)
	"ja-JP": /^(\+?81|0)\d{1,4}[ \-]?\d{1,4}[ \-]?\d{4}$/, //日语 (日本)
	"ms-MY": /^(\+?6?01){1}(([145]{1}(\-|\s)?\d{7,8})|([236789]{1}(\s|\-)?\d{7}))$/, //马来语 (马来西亚)
	"nb-NO": /^(\+?47)?[49]\d{7}$/, //挪威-伯克梅尔语 (挪威)
	"nl-BE": /^(\+?32|0)4?\d{8}$/, //荷兰语 (比利时)
	"nn-NO": /^(\+?47)?[49]\d{7}$/, //挪威-尼诺斯克语 (挪威)
	"pl-PL": /^(\+?48)? ?[5-8]\d ?\d{3} ?\d{2} ?\d{2}$/, //波兰语 (波兰)
	"pt-BR": /^(\+?55|0)\-?[1-9]{2}\-?[2-9]{1}\d{3,4}\-?\d{4}$/, //葡萄牙语 (巴西)
	"pt-PT": /^(\+?351)?9[1236]\d{7}$/, //葡萄牙语 (葡萄牙)
	"ru-RU": /^(\+?7|8)?9\d{9}$/, //俄语 (俄国)
	"sr-RS": /^(\+3816|06)[- \d]{5,9}$/, //塞尔维亚语 (塞尔维亚)
	"tr-TR": /^(\+?90|0)?5\d{9}$/, //土耳其语 (土耳其)
	"th-TH": /^(\+?0?66\-?)?\d{10}$/, //泰语 (泰国)
	"vi-VN": /^(\+?84|0)?((1(2([0-9])|6([2-9])|88|99))|(9((?!5)[0-9])))([0-9]{7})$/, //越南语 (越南)
	"zh-CN": /^(\+?0?86\-?)?1[345789]\d{9}$/, //简体中文 (中国)
	"zh-TW": /^(\+?886\-?|0)?9\d{8}$/, //繁体中文 (中国台湾)
	"zh-HK": /^(\+?852\-?)?[569]\d{3}\-?\d{4}$/, //繁体中文 (中国香港)
}

/**
 * @description 判断手机号是否有效(各国家版)
 * @param {Number|String} phone 想要判断的手机号
 * @param {String} place 想要判断哪个国家/地区的手机号,默认中国,zh-CN
 * @return {Boolean} 返回true或false,true为有效,false为无效
 */
function checkPhone(phone, place = "zh-CN") {
	if (!phoneObj[place].test(phone)) {
		console.log("手机号有误")
		return false
	} else {
		console.log("手机号正确")
		return true
	}
}

// 判断字符串是否是正整数包括0
function checkNumber(string) {
	if (!/^[0-9]*[1-9][0-9]*$/.test(string)) {
		console.log("不是正整数")
		return false
	} else {
		console.log("是正整数")
		return true
	}
}

/**
 * @description 封装uni-app 弹窗
 * @param {String} title 弹窗提示的文案
 * @param {Boolean} mask 弹出安是否开启防止触摸穿透
 * @param {String} icon 弹窗的样式
 * @param {Number} duration 弹窗的时间毫秒
 */
function showToast(title, mask = true, icon = "none", duration = 1500) {
	uni.hideLoading()
	uni.showToast({
		title: title,
		mask: mask,
		icon: icon,
		duration: duration,
	})
}

function showLoading(title = Vue.prototype.$t("加载中"), mask = true) {
	uni.showLoading({
		title: title,
		mask: mask,
	})
}

function showModal(title = "", content, confirmText = Vue.prototype.$t("确认"), cancelText = Vue.prototype.$t("取消"), showCancel = true) {
	return new Promise((resolve) => {
		uni.showModal({
			title: title,
			content: content,
			confirmText: confirmText,
			cancelText: cancelText,
			showCancel: showCancel,
			success: (res) => {
				if (res.confirm) {
					resolve(true)
				} else {
					resolve(false)
				}
			},
			fail: () => {
				resolve(false)
			},
		})
	})
}

// 判断是否是iphoneX及以上
function isIphoneX(that) {
	const phoneInfo = uni.getSystemInfoSync()
	phoneInfo.model = phoneInfo.model.toLowerCase()
	let phoneArr = ["iphone se", "iphone 3", "iphone 4", "iphone 5", "iphone 6", "iphone 7", "iphone 8"]
	let status = phoneArr.some((el) => phoneInfo.model.includes(el))
	that.isIPX = phoneInfo.model.includes("iphone") ? !status : false
	return that.isIPX
}

/**
 * @description  获取该元素的信息
 * @param {String} name 想要获取元素的 ID 或者 class
 * @return {Object} 获取的所有元素信息
 */
function getElementInfo(name) {
	let query = uni.createSelectorQuery()
	return new Promise((resolve) => {
		query
			.select(name)
			.boundingClientRect((rect) => {
				resolve(rect)
			})
			.exec()
	})
}

/**
 * @description  获取该元素的信息
 * @param {String} name 想要获取元素的 ID 或者 class
 * @return {Object} 获取的所有元素信息
 */
function getElementInfoAll(name) {
	let query = uni.createSelectorQuery()
	return new Promise((resolve) => {
		query
			.selectAll(name)
			.boundingClientRect((rect) => {
				resolve(rect)
			})
			.exec()
	})
}

/**
 * @description  获取该元素的信息
 * @param {String} name 想要获取元素的 ID 或者 class
 * @return {Object} 获取的所有元素信息
 */
function getElementIsVisible(name) {
	return new Promise((resolve) => {
		this.getElementInfo(name).then((res) => {
			// 判断元素是否在视口范围内
			const isVisible = res.top >= 0 && res.bottom <= $bus.windowHeight && res.left >= 0 && rect.right <= $bus.windowWidth
			if (isVisible) {
				// 元素可见
				resolve(true)
			} else {
				// 元素不可见
				resolve(false)
			}
		})
	})
}

/**
 * @description  获取图片信息
 * @param {String} url 图片的url
 * @return {Object} 获取的图片所有信息
 */
function getImageInfo(url) {
	return new Promise((resolve) => {
		uni.getImageInfo({
			src: url,
			success(res) {
				console.log("resresresres", res)
				resolve(res)
			},
			fail(err) {
				console.log(err)
				resolve(err)
			},
		})
	})
	// return
}

/**
 * @description  计算scroll-view高度
 * @param {Number} reduceHeight 想要减掉的高度
 * @return {Number} 返回计算后的scroll高度
 */
function computeScrollHeight(reduceHeight = 0) {
	let scrollHeight = $bus.screenHeight - ($bus.navTotalHeight + parseInt(reduceHeight) + ($bus.isIPX ? 28 : 0)) //nav栏height和padding一共的高度
	return scrollHeight
}

function computeScrollHeightWindow(reduceHeight = 0) {
	let scrollHeight = uni.getSystemInfoSync().windowHeight - ($bus.navTotalHeight + parseInt(reduceHeight)) //nav栏height和padding一共的高度
	return scrollHeight
}

function transformTime_8(timeStamp) {
	let date = new Date((parseInt(timeStamp) + 8 * 3600) * 1000) // 增加8小时
	return date.toJSON().substr(0, 19).replace("T", " ")
}

function transformTime(timeStamp) {
	let date = new Date(parseInt(timeStamp) * 1000)
	return date.toJSON().substr(0, 19).replace("T", " ")
}
/**
 * @description 精准判断数据类型
 * @param  data 想要判断的数据任意
 * @return {String} 返回这个元素的数据类型
 * *可能是 String Number Object Boolean Array Function
 * *      Undefined Null Date RegExp Error
 */
function getDataType(data) {
	let typeStr = Object.prototype.toString.call(data)
	let typeArr = typeStr.split(" ")
	let type = typeArr[1].replaceAll("]", "")
	return type
}
/**
 * @description 深拷贝数据
 * @param  data 想要深拷贝的数据
 * @return 返回深拷贝后的数据
 */
function deepCopy(data) {
	return JSON.parse(JSON.stringify(data))
}
/**
 * @description 移动数组某一项 array 数组,formIndex 数组所在的位置,formIndex 数组想要移动到的地方
 * @param  array 想要处理的数组
 * @param  {Number} formIndex 数组所在的位置
 * @param  {Number} toIndex 数组想要移动到的地方
 * @return 返回处理后的数组
 */
function moveArrElement(array, formIndex, toIndex) {
	let newArr = array.splice(formIndex, 1)
	array.splice(toIndex, 0, newArr[0])
	return array
}
/**
 * @description 解析 url 中的参数 返回Object
 * @param  {String} url 想要解析的参数
 * @return {Object}返回处理后的参数对象
 */
function convertUrl(url) {
	if (!url.includes("?")) {
		return
	}
	let urlArr = url.split("?")
	let paramArr = urlArr[1]
	paramArr = paramArr.split("&")
	let param = {}
	for (let i = 0; i < paramArr.length; i++) {
		let item = paramArr[i].split("=")
		param[item[0]] = item[1]
	}
	return param
}
/**
 * @description 解析 URL 中的参数转换成字符串传递下一页格式'?**=**'
 * @param  {String} params 想要解析url路径
 * @return {String} 解析后的url路径
 */
function changeParams(params) {
	let paramArr = Object.entries(params)
	if (paramArr.length == 0) {
		return
	}
	let paramStr = ""
	paramArr.forEach((el) => {
		paramStr = paramStr + `&${el[0]}=${el[1]}`
	})
	return paramStr.replace("&", "?")
}

//数组根据id去重
function setDataArr(arr, id = "id") {
	if (!Array.isArray(arr)) {
		// 判断是否是数组形式,不是，则抛出异常
		throw new Error("arr is not a array")
	}
	let data = JSON.parse(JSON.stringify(arr))
	for (let i = 0; i < data.length; i++) {
		for (let y = i + 1; y < data.length; y++) {
			if (data[y][id] === data[i][id]) {
				data.splice(y, 1)
				y -= 1
			}
		}
	}
	return data
}
/**
 * @description 解析scene字符串中的数据
 * @param  {String} params 想要解析scene数据
 * @return {Object} 解析后的对象
 */
function changeScene(scene) {
	scene = scene.split("&")
	let param = {}
	for (let i = 0; i < scene.length; i++) {
		let item = scene[i].split("=")
		param[item[0]] = item[1]
	}
	console.log(param)
	return param
}
// 跳转到其他小程序
function toMiniProgram(appid, path, data = {}) {
	uni.navigateToMiniProgram({
		appId: appid,
		path: path,
		extraData: data,
		success() {
			console.log("跳转其他小程序成功")
			// 打开成功
		},
	})
}
//返回当前页面栈
function currentPages(num = 1) {
	let currPages = getCurrentPages()[getCurrentPages().length - num]
	if (currPages) {
		return currPages.route
	}
}
//判断页面栈
function repeatPath(path) {
	if (path[0] == "/") {
		path = path.substr(1)
	}
	for (let i = 2; i <= 11; i++) {
		let currPages = getCurrentPages()[getCurrentPages().length - i]
		if (currPages && currPages.route == path.substr(1)) {
			return wx.navigateBack({
				delta: i - 1,
			})
		}
	}
}
//发送模板消息
function requestSubscribeMessage(tmplIds) {
	// ['GnHMRstSiOeqJSegszFJE32Mg497fYqQrd2QkSRJBsE', 'z29OKZgNL-pFP-tqHtbG5EUM9ACrwmvMA2NNfMHepSo', '4_NUoEeXDxNoAWT1MS_8YGWQAenk_odCNjH-HjKwvYw']
	return new Promise((resolve) => {
		uni.requestSubscribeMessage({
			tmplIds: tmplIds,
			success: (res) => {
				console.log("模板消息成功", res)
				console.log(res.data)
				resolve(true)
			},
			fail: (err) => {
				console.log("模板消息失败", err)
				resolve(false)
			},
		})
	})
}

// promise.all封装
function promiseAll(array, callback) {
	Promise.all(array)
		.then(() => {
			callback(true)
		})
		.catch(() => {
			callback(false)
		})
}

// 时间戳解析
function timeFormat(timestamp, formats = "Y-m-d H:i:s") {
	// formats格式包括
	// 1. Y-m-d
	// 2. Y-m-d H:i:s
	// 3. Y年m月d日
	// 4. Y年m月d日 H时i分
	timestamp = String(timestamp).replace(/-/g, "/")
	let zero = function (value) {
		return value < 10 ? (value = "0" + value) : value
	}
	if (String(timestamp).length == 10) {
		timestamp = timestamp * 1000
	}
	let myDate = timestamp ? new Date(timestamp) : new Date()
	let year = myDate.getFullYear()
	let month = zero(myDate.getMonth() + 1)
	let day = zero(myDate.getDate())
	let hour = zero(myDate.getHours())
	let minute = zero(myDate.getMinutes())
	let second = zero(myDate.getSeconds())
	return formats.replace(/Y|m|d|H|i|s/gi, function (matches) {
		return {
			Y: year,
			m: month,
			d: day,
			H: hour,
			i: minute,
			s: second,
		}[matches]
	})
}

/*
    判断日期是否在今天 
    示例：
     todayJudge(1669961510000, true)
     todayJudge("2023-04-16 21:45:00")
*/
function todayJudge(param, isTimestamp) {
	// 如果传入的时间戳是字符串，需要进行类型转换
	if (typeof param === "string" && isTimestamp) {
		param = Number(param)
	}
	if (!isTimestamp) {
		// ios日期时间兼容
		param = param.replace(/-/g, "/")
	}
	var currentStamp = new Date().setHours(0, 0, 0, 0) // 当天日期，转换为时间部分为0的时间戳
	var paramStamp = new Date(param).setHours(0, 0, 0, 0) // 传入时间戳，将时间部分转换为0
	// 若两个时间戳相等，说明传入的时间戳即今天
	if (currentStamp == paramStamp) {
		return true
	}
	return false
}

// 返回星期几
function getWeek(date, state) {
	date = date.replace(/-/g, "/")
	let weekIndex = new Date(date).getDay()
	let showLabe = state ? "周" : "星期"
	let w = ["日", "一", "二", "三", "四", "五", "六"]
	return showLabe + w[weekIndex]
}

// 数字处理成金额
function toMoney(num) {
	if (num) {
		if (isNaN(num)) {
			console.log("金额中含有不能识别的字符")
			return
		}
		num = typeof num == "string" ? parseFloat(num) : num // 判断是否是字符串如果是字符串转成数字
		num = num.toFixed(2) // 保留两位
		num = parseFloat(num) // 转成数字
		num = num.toLocaleString() // 转成金额显示模式
		// 判断是否有小数
		if (num.indexOf(".") === -1) {
			num = num + ".00"
		} else {
			// console.log(num.split('.')[1].length,num)
		}
		return num // 返回的是字符串23,245.12保留2位小数
	} else {
		if (num === 0) return 0
		return (num = null)
	}
}

// js 精度计算 加法
function accAdd(arg1, arg2) {
	var r1, r2, m, c
	try {
		r1 = arg1.toString().split(".")[1].length
	} catch (e) {
		r1 = 0
	}
	try {
		r2 = arg2.toString().split(".")[1].length
	} catch (e) {
		r2 = 0
	}
	c = Math.abs(r1 - r2)
	m = Math.pow(10, Math.max(r1, r2))
	if (c > 0) {
		var cm = Math.pow(10, c)
		if (r1 > r2) {
			arg1 = Number(arg1.toString().replace(".", ""))
			arg2 = Number(arg2.toString().replace(".", "")) * cm
		} else {
			arg1 = Number(arg1.toString().replace(".", "")) * cm
			arg2 = Number(arg2.toString().replace(".", ""))
		}
	} else {
		arg1 = Number(arg1.toString().replace(".", ""))
		arg2 = Number(arg2.toString().replace(".", ""))
	}
	return (arg1 + arg2) / m
}

// 判断时间间隔多少小时
function timeDifference(endTime, startTime = parseInt(Date.now() / 1000)) {
	let time = (endTime - startTime) / 60 / 60 / 24
	if (time > -1 && time <= 0) {
		return -1
	} else if (time > 0 && time <= 1) {
		return 1
	} else {
		return parseInt(time)
	}
}
// 日期转时间戳
function dateToTime(date) {
	return parseInt(new Date(date).getTime() / 1000)
}

// 获取当前日期时间戳
function getCurrentTime() {
	return parseInt(Date.now() / 1000)
}

//传值 url中传递值转换%25
function passData(data) {
	return encodeURIComponent(JSON.stringify(data))
}

//接值 在onLoad中
function receiveData(data) {
	return JSON.parse(decodeURIComponent(changeJSON(data)))
}

// 转换JSON 把% 转换为%25
function changeJSON(data) {
	if (data.indexOf("%") > -1) {
		return data.replace(/%/g, "%25")
	} else {
		return data
	}
}

/**
 * @description 向APP发送数据(H5)
 * @param  methodName APP端接收的方法名
 * @param  data APP端接收的参数 (最终会被转换为JSON)
 */
function sendDataToApp(methodName, data = {}) {
	let u = navigator.userAgent
	let isAndroid = u.indexOf("Android") > -1 || u.indexOf("Linux") > -1 //android终端或者uc浏览器
	let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
	if (isAndroid) {
		window.android[methodName](JSON.stringify(data))
	} else if (isIOS) {
		window.webkit.messageHandlers[methodName].postMessage(JSON.stringify(data))
	}
}

// 处理活动详情日期
function handleActDetailDate(dateStr, dateList, symbol='-'){
    let showDate = ""
    if (dateList && dateList.length > 1) {
        showDate = dateList[0]?.slice(0,10) + " " + symbol + " " + dateList[dateList.length - 1]?.slice(0,10)
    } else {
        showDate = dateStr
    }
    return showDate
}

// 复制快递单号
function copyText(text) {
	uni.setClipboardData({
		data: text.toString(),
		success: function () {},
	})
}
// 年月日转成月日
function newDate(date) {
	// 原始的年月日格式
	let originalDate = date
	// 将年月日字符串转换为Date对象
	let dateObj = new Date(originalDate)
	// 获取月份和日期
	let month = dateObj.getMonth() + 1 // 月份是从0开始计数的，需要加1
	let day = dateObj.getDate()
	// 构造月日格式字符串
	let monthDayFormat = month + "." + day
	return monthDayFormat
}


function deepClone(obj) {
    if (typeof obj == "object") {
        if (Array.isArray(obj)) {
            let arr = [];
            for (let item of obj) {
                arr.push(Object.assign(deepClone(item)));
            }
            return arr;
        } else if (obj == null) {
            return null;
        } else {
            let obj1 = {};
            for (let index in obj) {
                obj1[index] = deepClone((obj[index]));
            }
            return obj1;
        }
    } else if (typeof obj == "function") {
        return Object.assign(obj);
    } else if (typeof obj == undefined) {
        return undefined;
    } else {
        return obj;
    }
}

export default {
	checkPhone, // 判断手机号
	checkNumber, // 判断正整数
	showToast, // 弹窗提示
	showLoading, // 弹窗Loading
	showModal, // 弹窗Modal
	isIphoneX, // 判断是否是iphoneX及以上
	getElementInfo, //获取该元素的信息
	getElementInfoAll, //获取该元素的信息
	getElementIsVisible, //判断元素是否可见
	computeScrollHeight, //计算scroll-view高度
	computeScrollHeightWindow, //计算scroll-view高度(使用windowHeight计算)
	transformTime, //时间戳格式化函数
	transformTime_8, //时间戳格式化函数 8小时
	getDataType, //判断数据类型
	deepCopy, //深拷贝
	moveArrElement, //移动数组元素
	convertUrl, //解析 url 中的参数 返回Object
	changeParams, //解析 URL 中的参数转换成字符串传递下一页格式'?**=**'
	getImageInfo, //获取图片信息
	setDataArr, //数组根据id去重
	changeScene, //解析scene字符串中的数据
	toMiniProgram, //跳转到其他小程序
	currentPages, //返回当前页面栈
	repeatPath, //判断页面栈
	requestSubscribeMessage, //发送模板消息
	promiseAll, //promise.all封装
	timeFormat, //时间戳解析
	todayJudge, // 判断是否是今天
	getWeek, //返回星期/周几
	toMoney, // 数字处理成金额
	accAdd,
	timeDifference, //判断时间间隔多少小时
	dateToTime, //日期转时间戳
	getCurrentTime, //获取当前日期时间戳
	passData, //传值 url中传递值转换%25
	receiveData, //接值 在onLoad中
	sendDataToApp, //向APP发送数据(H5)
	copyText, //复制文本
	newDate, //月日
    deepClone, //深拷贝
    handleActDetailDate, //处理活动详情页日期
}
